home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HPAVC
/
HPAVC CD-ROM.iso
/
MCASM.RAR
/
MC_ASM.EXE
/
WROX_ASM
/
CH10
/
PROGRAMS
/
ARHH6.ASM
< prev
next >
Wrap
Assembly Source File
|
1994-05-30
|
12KB
|
667 lines
; Haffman coding
; Written by Malakhov K.A.
; Compile with TASM 3.0 or latter
; TASM ARHH6.ASM /MX /ZX /O
; CALL: haff_encode(char *buffinput,unsigned int inputlength,
; char *buffoutput,unsigned int outputlength);
model large
PUBLIC _haff_encode
.code
; Haffman compression
_haff_encode PROC C FAR
ARG buffi:dword,ileng:word,buffo:dword,oleng:word
USES ds,es,di,si,bx,cx,dx
cld
mov ax,oleng
mov cs:counto,ax
@@implode_1:
; Procedure of bilding the tree
call rdtree
cmp ax,0
je @@implode_n
; Provedure of coding
call arhhaff
@@implode_n: ret
rdtree proc NEAR
; Initialize
mov ax,ileng
mov cs:counti,ax
mov cs:CRCod,0
; Fill the table of characters
mov cx,256
xor al,al
push cs
pop es
lea di,chartab
@@impl_015: stosb
inc al
loop @@impl_015
; clear hafftab & freqtab
mov cx,1024
xor al,al
lea di,hafftab
rep stosb
mov cx,256
lea di,freqtab
xor ax,ax
rep stosw
mov cs:codcnt,0
; Calculate the number of repeat bytes in file
lea di,freqtab
mov ax,word ptr buffi+2
mov ds,ax
mov si,word ptr buffi
mov cx,cs:counti
@@impl_020: lodsb
add cs:CRCod,al
xor ah,ah
shl ax,1
mov bx,ax
add bx,di
inc word ptr es:[bx]
loop @@impl_020
; Sort
mov cx,256
xor di,di
xor dl,dl
@@impl_030: push cx
dec cx
mov si,di
add si,2
mov dh,dl
inc dh
@@impl_040: push cx
mov ax,word ptr cs:freqtab[di]
cmp ax,0
jne @@impl_050
mov ax,word ptr cs:freqtab[si]
cmp ax,0
je @@impl_060
mov bx,word ptr cs:freqtab[di]
mov word ptr cs:freqtab[si],bx
mov word ptr cs:freqtab[di],ax
mov bl,dh
xor bh,bh
mov al,byte ptr cs:chartab[bx]
mov bl,dl
mov ah,byte ptr cs:chartab[bx]
mov bl,dh
mov byte ptr cs:chartab[bx],ah
mov bl,dl
mov byte ptr cs:chartab[bx],al
@@impl_050: mov ax,word ptr cs:freqtab[di]
mov bx,word ptr cs:freqtab[si]
cmp bx,0
je @@impl_060
cmp ax,bx
jbe @@impl_060
mov word ptr cs:freqtab[si],ax
mov word ptr cs:freqtab[di],bx
mov bl,dh
xor bh,bh
mov al,byte ptr cs:chartab[bx]
mov bl,dl
mov ah,byte ptr cs:chartab[bx]
mov bl,dh
mov byte ptr cs:chartab[bx],ah
mov bl,dl
mov byte ptr cs:chartab[bx],al
@@impl_060: add si,2
inc dh
pop cx
dec cx
jz @@impl_070
jmp @@impl_040
@@impl_070: add di,2
inc dl
pop cx
dec cx
cmp cx,1
jbe @@impl_080
jmp @@impl_030
@@impl_080:
; Calculating the number of different symbols
mov cx,256
push cs
pop ds
lea si,freqtab
mov cs:hafflen,0
@@impl_085: lodsw
cmp ax,0
je @@impl_088
inc word ptr cs:hafflen
loop @@impl_085
@@impl_088:
; Init
mov ax,word ptr buffo+2
mov es,ax
mov di,word ptr buffo
; Store CRC
mov al,cs:CRCod
stosb
dec word ptr cs:counto
; Store the length of header
mov ax,cs:hafflen
dec ax
stosb
dec word ptr cs:counto
; Store header
mov cx,cs:hafflen
xor si,si
@@impl_0880: mov al,cs:chartab[si]
stosb
dec word ptr cs:counto
inc si
loop @@impl_0880
mov cx,cs:hafflen
xor si,si
@@impl_0881: mov ax,cs:freqtab[si]
stosw
dec word ptr cs:counto
dec word ptr cs:counto
add si,2
loop @@impl_0881
mov cs:savedi,di
; Building the tree
; Prepare the table of weights
mov cx,256
push cs
pop es
lea di,codtab
xor al,al
rep stosb
; MIN
@@impl_089: mov bx,65535
xor si,si
mov cx,cs:hafflen
@@impl_090: mov ax,cs:freqtab[si]
cmp ax,0
je @@impl_092
cmp bx,ax
jbe @@impl_092
mov bx,ax
mov cs:minpos1,si
@@impl_092: add si,2
loop @@impl_090
mov cs:exit,1
mov bx,65535
xor si,si
mov cx,cs:hafflen
cmp cx,1
ja @@impl_094
mov ax,cs:minpos1
shr ax,1
mov cl,1
call shift
jmp @@impl_220
@@impl_094: mov ax,cs:freqtab[si]
cmp ax,0
je @@impl_096
cmp bx,ax
jb @@impl_096
cmp si,cs:minpos1
je @@impl_096
mov bx,ax
mov cs:exit,0
mov cs:minpos2,si
@@impl_096: add si,2
loop @@impl_094
mov al,cs:exit
cmp al,0
je @@impl_098
jmp @@impl_220
@@impl_098:
mov ax,cs:minpos1
shr ax,1
mov si,ax
mov ax,cs:minpos2
shr ax,1
mov di,ax
mov al,cs:codtab[si]
mov ah,cs:codtab[di]
cmp al,0
jne @@impl_100
cmp ah,0
je @@impl_099
jmp @@impl_125
; Variant 1
@@impl_099: inc byte ptr cs:codcnt
mov ax,si
mov cl,0
call shift
mov ax,di
mov cl,1
call shift
mov al,cs:codcnt
mov cs:codtab[si],al
mov cs:codtab[di],al
mov si,cs:minpos1
mov di,cs:minpos2
mov ax,cs:freqtab[di]
add cs:freqtab[si],ax
mov cs:freqtab[di],0
jmp @@impl_089
; Variant 2
@@impl_100:
cmp ah,0
je @@impl_102
jmp @@impl_140
@@impl_102:
mov ax,cs:minpos1
shr ax,1
mov si,ax
mov dl,cs:codtab[si]
mov cx,256
xor si,si
@@impl_105: cmp dl,cs:codtab[si]
jne @@impl_110
push cx
mov ax,si
xor cl,cl
call shift
pop cx
@@impl_110: inc si
loop @@impl_105
mov ax,cs:minpos2
shr ax,1
mov cl,1
call shift
mov ax,cs:minpos1
shr ax,1
mov si,ax
mov ax,cs:minpos2
shr ax,1
mov di,ax
mov al,cs:codtab[si]
mov cs:codtab[di],al
mov si,cs:minpos1
mov di,cs:minpos2
mov ax,cs:freqtab[di]
add cs:freqtab[si],ax
mov cs:freqtab[di],0
jmp @@impl_089
@@impl_125:
mov ax,cs:minpos2
shr ax,1
mov si,ax
mov dl,cs:codtab[si]
mov cx,256
xor si,si
@@impl_130: cmp dl,cs:codtab[si]
jne @@impl_135
push cx
mov ax,si
xor cl,cl
call shift
pop cx
@@impl_135: inc si
loop @@impl_130
mov ax,cs:minpos1
shr ax,1
mov cl,1
call shift
mov ax,cs:minpos2
shr ax,1
mov si,ax
mov ax,cs:minpos1
shr ax,1
mov di,ax
mov al,cs:codtab[si]
mov cs:codtab[di],al
mov si,cs:minpos2
mov di,cs:minpos1
mov ax,cs:freqtab[di]
add cs:freqtab[si],ax
mov cs:freqtab[di],0
jmp @@impl_089
; Variant 3
@@impl_140:
mov ax,cs:minpos1
shr ax,1
mov si,ax
mov dl,cs:codtab[si]
mov cx,256
xor si,si
@@impl_145: cmp dl,cs:codtab[si]
jne @@impl_150
push cx
mov ax,si
xor cl,cl
call shift
pop cx
@@impl_150: inc si
loop @@impl_145
mov ax,cs:minpos2
shr ax,1
mov si,ax
mov dl,cs:codtab[si]
mov cx,256
xor si,si
@@impl_155: cmp dl,cs:codtab[si]
jne @@impl_160
push cx
mov ax,si
mov cl,1
call shift
pop cx
@@impl_160: inc si
loop @@impl_155
mov ax,cs:minpos1
shr ax,1
mov si,ax
mov dl,cs:codtab[si]
mov ax,cs:minpos2
shr ax,1
mov si,ax
mov dh,cs:codtab[si]
mov cx,256
xor si,si
@@impl_165: cmp dl,cs:codtab[si]
jne @@impl_170
mov cs:codtab[si],dh
@@impl_170: inc si
loop @@impl_165
mov si,cs:minpos2
mov di,cs:minpos1
mov ax,cs:freqtab[di]
add cs:freqtab[si],ax
mov cs:freqtab[di],0
jmp @@impl_089
; Calculating the number of bytes
@@impl_220: mov di,2
mov cx,256
@@impl_230: mov al,cs:hafftab[di]
xor ah,ah
xor dx,dx
mov bx,8
div bx
mov cs:hafftab[di],8
cmp dx,0
je @@impl_240
mov cs:hafftab[di],dl
inc ax
@@impl_240: mov cs:hafftab[di+1],al
add di,4
loop @@impl_230
; Calculating the length of archieve
mov ax,word ptr buffo+2
mov ds,ax
mov si,word ptr buffo
mov cx,cs:hafflen
add si,cx
add si,2
push cs
pop es
lea di,freqtab
rep movsw
mov cs:fulleng,0
mov cs:fullenb,0
mov cx,256
xor bx,bx
@@impl_2400: push cx
mov dl,cs:hafftab[bx+3]
cmp dl,0
ja @@impl_2401
jmp @@impl_2406
@@impl_2401: dec dl
xor dh,dh
mov ax,bx
mov cl,2
shr ax,cl
mov cx,256
xor si,si
@@impl_2402: mov ah,cs:chartab[si]
cmp ah,al
je @@impl_2403
inc si
loop @@impl_2402
@@impl_2403: shl si,1
mov cx,cs:freqtab[si]
cmp dx,0
je @@impl_2404
mov ax,dx
xor dx,dx
mul cx
add cs:fulleng,ax
@@impl_2404: mov al,cs:hafftab[bx+2]
xor ah,ah
mul cx
mov cx,8
xor dx,dx
div cx
add cs:fulleng,ax
add dx,cs:fullenb
cmp dx,8
jb @@impl_2405
sub dx,8
inc word ptr cs:fulleng
@@impl_2405: mov cs:fullenb,dx
@@impl_2406: add bx,4
pop cx
dec cx
jz @@impl_2407
jmp @@impl_2400
@@impl_2407: mov ax,cs:fullenb
cmp ax,0
je @@impl_2408
inc word ptr cs:fulleng
@@impl_2408: mov ax,cs:fulleng
mov bx,cs:hafflen
shl bx,1
add bx,cs:hafflen
add ax,bx
add ax,2
cmp ax,cs:counti
jae @@impl_err
@@impl_noerr: mov ax,1
jmp @@impl_exi
@@impl_err: xor ax,ax
@@impl_exi: ret
rdtree endp
; Compression
arhhaff proc NEAR
mov cs:shiftb,0
mov ax,word ptr buffi+2
mov ds,ax
mov si,word ptr buffi
mov ax,word ptr buffo+2
mov es,ax
mov di,word ptr cs:savedi
@@impl_250: mov ax,cs:counti
cmp ax,0
ja @@impl_270
mov al,cs:shiftb
cmp al,0
je @@impl_255
dec word ptr cs:counto
@@impl_255: jmp @@impl_320
@@impl_260: mov cs:counti,ax
mov si,word ptr buffi
@@impl_270: lodsb
dec word ptr cs:counti
xor ah,ah
mov cl,2
shl ax,cl
mov bx,ax
mov cs:currhaff,ax
mov ch,byte ptr cs:hafftab[bx+3]
cmp ch,1
ja @@impl_275
jmp @@impl_300
@@impl_275: dec ch
@@impl_280: mov dl,byte ptr es:[di]
; Mask
mov ax,0ff00h
mov cl,byte ptr cs:shiftb
shr ax,cl
and dl,al
; Code
mov ah,byte ptr cs:hafftab[bx]
xor al,al
mov cl,byte ptr cs:shiftb
shr ax,cl
or ah,dl
mov byte ptr es:[di],ah
push ax
inc di
dec word ptr cs:counto
mov ax,cs:counto
cmp ax,0
ja @@impl_290
jmp @@implode_err
@@impl_290: pop ax
mov byte ptr es:[di],al
inc bx
dec ch
jz @@impl_300
jmp @@impl_280
; Last byte
@@impl_300: mov dl,byte ptr es:[di]
; Mask
mov ax,0ff00h
mov cl,byte ptr cs:shiftb
shr ax,cl
and dl,al
; Code
mov ah,byte ptr cs:hafftab[bx]
xor al,al
mov cl,byte ptr cs:shiftb
shr ax,cl
or ah,dl
mov byte ptr es:[di],ah
mov dx,ax
; Calculating the next shift
mov bx,cs:currhaff
add bx,2
mov al,cs:shiftb
add al,cs:hafftab[bx]
mov cs:shiftb,al
cmp al,8
jb @@impl_315
sub al,8
mov cs:shiftb,al
inc di
dec word ptr cs:counto
mov ax,cs:counto
cmp ax,0
ja @@impl_310
jmp @@implode_err
@@impl_310: mov ax,dx
mov byte ptr es:[di],al
@@impl_315: jmp @@impl_250
@@impl_320: mov ax,oleng
sub ax,cs:counto
cmp ax,0
ja @@impl_330
inc ax
@@impl_330: ret
@@implode_err: xor ax,ax
jmp short @@impl_exit
@@implode_noerr:
@@impl_exit: ret
arhhaff endp
; Procedure of shifting bits
shift proc NEAR
push bx
push di
push dx
rcr cl,1
pushf
mov bx,ax
mov al,cs:chartab[bx]
xor ah,ah
mov cl,2
shl ax,cl
mov di,ax
xor bx,bx
mov dx,bx
add dx,1
@@shift_010: cmp bx,dx
ja @@shift_020
mov al,cs:hafftab[di+bx]
popf
rcr al,1
pushf
mov cs:hafftab[di+bx],al
inc bx
jmp short @@shift_010
@@shift_015: mov cs:errflag,1
jmp short @@shift_030
@@shift_020: popf
mov cl,byte ptr cs:hafftab[di+bx]
cmp cl,16
ja @@shift_015
@@shift_030: inc byte ptr cs:hafftab[di+bx]
pop dx
pop di
pop bx
ret
shift endp
; DATA
counti dw ? ; Input bytes counter
counto dw ? ; Output bytes counter
savedi dw ?
hafflen dw ?
errflag db ?
shiftb db ? ; Shift bytes
currhaff dw ?
minpos1 dw ?
minpos2 dw ?
codcnt db ? ; Size of code
exit db ?
fulleng dw ? ; Full length
fullenb dw ? ; Full length in bytes
CRCod db ?
ident db 4dh,53h,49h
freqtab dw 257 dup(0) ; Table of probability
chartab db 257 dup(?) ; Table of characters
codtab db 256 dup(?) ; Table of index
hafftab db 1024 dup(?) ; Table of codes
@@imp_err: xor ax,ax
jmp short @@imp_exit
@@imp_noerr:
@@imp_exit: ret
_haff_encode ENDP
END